function [Results]=image_labels(image, models_struct, gui_param_struct)

% This function is the main function of the project - 
% here we take one image and trying to classify each pixel  based on a trained database - the models struct.

% Function Inputs:
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% image - RGB image matrix
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% models_struct - struct of the region classifier's output - can be one from the kind of -  
%       FLD, KNN, AdaBoost or any kind of mix models. 
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% gui_param_struct - struct with parameters obtain from an extrenal source like GUI.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

% Function Outputs:
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
% Results - output struct that contains some results based on the debug_flag. It can contain - 
%
%       labeling_grade - an absolute confidence grade of the image labeling system.
%       ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
%       segment_labels_map - the proposal label's map. 
%                   each pixel is defined by - 
%                                                               0 - Undefined Object
%                                                               1 - Sky
%                                                               2 - Vertical Object
%                                                               3 - Gradient Object
%                                                               4 - Ground
%       ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
%       vote_per_reg_cell - a cell that contains the votes for each region in each hypothese.
%       ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
%       confidence_cell -  a cell that contains the confidence of the classifier for each vote.
%       ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
%       seg_labels_tables - 3 tables of voting, each table is labelsXseg_count. there is table for polling
%       (max votes count), max_value (max confidence value) and sum_value (sum of confidence values).
%       ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
%       seg_map - the map of segments. 
%       ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
%       res - a struct of all data taken from the image, the output of get_struct function.
%-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

% Global Inputs:
% label_p.debug_flag
% label_p.norm_flag_seg
% label_p.norm_flag_reg
% label_p.hypo_option
% label_p.hypo_amount
% label_p.reg_per_hypo
% label_p.bw_factor
% label_p.med_filter
% label_p.image_resize_flag
% label_p.image_resize_factor
% label_p.classifier_mix
% label_p.voting_style
% model_p.reg_per_hypo
% model_p.hypo_amount
% model_p.class_func

% setting parameters
run parameters 
global label_p
global model_p

if (nargin == 3)
    label_p.hypo_amount          = gui_param_struct.hypo_amount;
    label_p.reg_per_hypo         = gui_param_struct.reg_per_hypo;
    label_p.segment_voting_style = gui_param_struct.segment_voting_style;    
    model_p.class_func           = gui_param_struct.class_func;       
end

class_func=model_p.class_func;
classifier_mix=label_p.classifier_mix;
debug_flag=label_p.debug_flag;
norm_flag_seg=label_p.norm_flag_seg;
norm_flag_reg=label_p.norm_flag_reg;
hypo_option=label_p.hypo_option;
bw_factor=label_p.bw_factor;
med_filter=label_p.med_filter;
resize_flag=label_p.image_resize_flag;
resize_factor=label_p.image_resize_factor;
hypo_amount=label_p.hypo_amount;
reg_per_hypo=label_p.reg_per_hypo;
voting_style=label_p.segment_voting_style;

% running pre proccessing if needed
if strcmp(resize_flag,'true')
    image=imfilter(image,fspecial('gaussian',[200,200]),0.3);
    image=imresize(image,resize_factor,'bilinear');
end

% using function get_struct to calc all segments and regions features
[res]=get_struct(image,norm_flag_seg,norm_flag_reg,hypo_option,hypo_amount,reg_per_hypo,bw_factor,med_filter);

% deciding for each region what label is it
if strcmp(classifier_mix,'false')
    [vote_per_reg_cell,confidence_cell]=vote_per_reg(res.reg_features_cell,models_struct);
    reg_indices=res.reg_indices;
end

if strcmp(classifier_mix,'true')
    counter=1;
    % getting out all classifier's names
    models=fieldnames(models_struct);
    for i=1:length(models)
        % getting the right classifier
        if (size(strfind(lower(models{i}),'fld'),1)==1)   model_p.class_func='FLD'; end
        if (size(strfind(lower(models{i}),'knn'),1)==1)   model_p.class_func='KNN'; end
        if (size(strfind(lower(models{i}),'real'),1)==1)  model_p.class_func='RealAdaBoost'; end
        if (size(strfind(lower(models{i}),'modest'),1)==1)  model_p.class_func='ModestAdaBoost'; end
        eval(sprintf('[vote,conf]=vote_per_reg(res.reg_features_cell,models_struct.%s);',models{i}));
        for k=1:size(vote,1)
             vote_per_reg_cell{counter,1}=vote{k};
             confidence_cell{counter,1}=conf{k};
             reg_indices{counter,1}=res.reg_indices{k};
             counter=counter+1;
        end
    end
end

% deciding for each segment(and actually each pixel) what label is it
[segment_labels_map,seg_labels_tables]=segment_labels(res.seg_map, vote_per_reg_cell,res.seg_indices,reg_indices,confidence_cell);

% resizing the image back if needed
if strcmp(resize_flag,'true')
    segment_labels_map=round(imresize(segment_labels_map,1/resize_factor,'bilinear'));
end

% setting the result struct
Results.segment_labels_map=segment_labels_map;
if (strcmp(class_func,'KNN')==0)
    switch voting_style
        case 'polling'
            Results.labeling_grade=segment_map_grade(res.seg_indices,seg_labels_tables.polling,seg_labels_tables.sum_value);
        case 'max_value'
           Results.labeling_grade=segment_map_grade(res.seg_indices,seg_labels_tables.max_value,seg_labels_tables.sum_value);
        case 'sum_value'
            Results.labeling_grade=segment_map_grade(res.seg_indices,seg_labels_tables.sum_value,seg_labels_tables.sum_value);
    end
else
    Results.labeling_grade=mean(max(seg_labels_tables.polling))/(hypo_amount*size(reg_per_hypo,2));
end
if strcmp(classifier_mix,'true')
    Results.labeling_grade=mean(max(seg_labels_tables.polling))/(hypo_amount*size(reg_per_hypo,2)*i);
end
if (debug_flag==1 || debug_flag==2)
    Results.vote_per_reg_cell=vote_per_reg_cell;
    Results.confidence_cell=confidence_cell;
    Results.seg_labels_tables=seg_labels_tables;
    if (debug_flag==1)
        Results.seg_map=res.seg_map;
    else
        Results.res=res;
    end
end
